/*
 *    Copyright (c) 2018-2025, boss All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the boss developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: boss
 */
package com.hopes.bizz.close.basic.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.hopes.bizz.close.basic.dto.*;
import com.hopes.bizz.close.basic.entity.ClosedPersonCompanyEntity;
import com.hopes.bizz.close.basic.service.ClosedOperateAuditRecordService;
import com.hopes.bizz.close.basic.vo.ClosedPersonCompanyExcelVO;
import com.hopes.bizz.close.basic.mapper.ClosedPsersonCompanyMapper;
import com.hopes.bizz.close.basic.service.ClosedPersonCompanyService;
import com.hopes.bizz.close.common.constant.BasicDicConstant;
import com.hopes.bizz.close.common.constant.CloseModuleEnums;
import com.hopes.bizz.close.common.constant.VisitorDicConstant;
import com.hopes.bizz.close.common.constant.enums.ParkCloseSysDictEnum;
import com.hopes.bizz.common.core.validate.ValidatorUtils;
import com.hopes.boss.admin.api.dto.UserDTO;
import com.hopes.boss.admin.api.entity.SysUser;
import com.hopes.boss.admin.api.feign.RemoteUserService;
import com.hopes.boss.admin.api.resolver.DictResolver;
import com.hopes.boss.admin.api.resolver.enums.AdminDictEnum;
import com.hopes.boss.common.core.exception.BizException;
import com.hopes.boss.common.core.util.R;
import com.hopes.boss.common.entity.ValidateImportBO;
import com.hopes.boss.common.excel.vo.ErrorMessage;
import com.hopes.boss.common.security.util.SecurityUtils;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 企业人员信息
 *
 * @author pig
 * @date 2024-02-20 13:41:07
 */
@Service
@RequiredArgsConstructor
public class ClosedPersonCompanyServiceImpl extends ServiceImpl<ClosedPsersonCompanyMapper, ClosedPersonCompanyEntity> implements ClosedPersonCompanyService {

    private final RemoteUserService remoteUserService;
    private final ClosedOperateAuditRecordService closedOperateAuditRecordService;

    @Override
    public boolean save(ClosedPersonCompanyEntity entity) {
        entity.setApplyUserId(SecurityUtils.getUserId());
        if (ObjUtil.isNull(entity.getApplyTime())) {
            entity.setApplyTime(Calendar.getInstance().getTime());
        }
        entity.setAuditStatus(VisitorDicConstant.CLOSE_VISITOR_AUDIT_STATUS_NOT_SUBMIT);
        return SqlHelper.retBool(getBaseMapper().insert(entity));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean submitById(Long id) {
        // 1、修改状态
        lambdaUpdate()
                .set(ClosedPersonCompanyEntity::getAuditStatus, BasicDicConstant.CLOSE_PERSON_AUDIT_STATUS_NOT_AUDIT)
                .eq(ClosedPersonCompanyEntity::getId, id).update();
        // 2、创建提交日志记录
        return closedOperateAuditRecordService.buildSaveOperateAuditRecord(id,
                CloseModuleEnums.GeneralCarOperateEnum.submit.getValue(),
                BasicDicConstant.CLOSE_PERSON_AUDIT_STATUS_NOT_AUDIT, null, null);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveAndSubmit(ClosedPersonCompanyEntity closedPersonCompany) {
        // 1、保存企业人员
        closedPersonCompany.setApplyUserId(SecurityUtils.getUserId());
        if (ObjUtil.isNull(closedPersonCompany.getApplyTime())) {
            closedPersonCompany.setApplyTime(Calendar.getInstance().getTime());
        }
        closedPersonCompany.setAuditStatus(VisitorDicConstant.CLOSE_VISITOR_AUDIT_STATUS_NOT_AUDIT);
        if (ObjUtil.isNull(closedPersonCompany.getId())) {
            getBaseMapper().insert(closedPersonCompany);
        } else {
            getBaseMapper().updateById(closedPersonCompany);
        }
        // 2、创建 && 提交日志
        return closedOperateAuditRecordService.buildSaveOperateAuditRecord(closedPersonCompany.getId(),
                CloseModuleEnums.GeneralCarOperateEnum.audit.getValue(),
                BasicDicConstant.CLOSE_PERSON_AUDIT_STATUS_NOT_AUDIT, null, null);
    }

    @Override
    public boolean auditById(ClosedPersonCompanyAuditDTO closedPersonCompanyAuditDTO) {
        // 1、修改对象
        lambdaUpdate()
                .set(ClosedPersonCompanyEntity::getRemark, closedPersonCompanyAuditDTO.getRemark())
                .set(ClosedPersonCompanyEntity::getAuditStatus, closedPersonCompanyAuditDTO.getAuditStatus())
                .set(ClosedPersonCompanyEntity::getAuditResultDesc, closedPersonCompanyAuditDTO.getAuditStatusDesc())
                .eq(ClosedPersonCompanyEntity::getId, closedPersonCompanyAuditDTO.getId()).update();

        // 2、创建 && 提交日志
        return closedOperateAuditRecordService.buildSaveOperateAuditRecord(
                closedPersonCompanyAuditDTO.getId(),
                CloseModuleEnums.GeneralCarOperateEnum.audit.getValue(),
                closedPersonCompanyAuditDTO.getAuditStatus(), closedPersonCompanyAuditDTO.getAuditStatusDesc(), closedPersonCompanyAuditDTO.getRemark());
    }

    @Override
    @GlobalTransactional
    @Transactional(rollbackFor = Exception.class)
    public boolean removeBindAccount(Long id) {
        final ClosedPersonCompanyEntity closedPersonCompany = getBaseMapper().selectById(id);
        if (ObjUtil.isNull(closedPersonCompany) || ObjUtil.isNull(closedPersonCompany.getAccountId())) {
            throw new BizException("获取企业人员信息异常");
        }
        final Long accountId = closedPersonCompany.getAccountId();
        final R<Boolean> booleanR = remoteUserService.userDel(new Long[]{accountId});
        if (!booleanR.success() || ObjUtil.isNull(booleanR.getData())) {
            throw new BizException("删除账号信息异常");
        }
        return lambdaUpdate().set(ClosedPersonCompanyEntity::getAccountId, null).eq(ClosedPersonCompanyEntity::getId, id).update();
    }

    @Override
    @GlobalTransactional
    @Transactional(rollbackFor = Exception.class)
    public boolean bindAccount(ClosedPersonCompanyBindAccountDTO closedPersonCompanyBindAccountDTO) {
        final Long companyPersonId = closedPersonCompanyBindAccountDTO.getCompanyPersonId();
        final ClosedPersonCompanyEntity closedPersonCompanyEntity = getBaseMapper().selectById(companyPersonId);
        final UserDTO userDTO = new UserDTO();
        userDTO.setUserType("company");
        userDTO.setName(closedPersonCompanyEntity.getName());
        userDTO.setOrgId(closedPersonCompanyEntity.getOrgId());
        userDTO.setRole(closedPersonCompanyBindAccountDTO.getRole());
        userDTO.setUsername(closedPersonCompanyBindAccountDTO.getUsername());
        userDTO.setPassword(closedPersonCompanyBindAccountDTO.getPassword());
        final R<SysUser> sysUserR = remoteUserService.bindUser(userDTO);
        if (!sysUserR.success() || ObjUtil.isNull(sysUserR.getData())) {
            throw new BizException("保存账号信息异常");
        }
        return lambdaUpdate().set(ClosedPersonCompanyEntity::getAccountId, sysUserR.getData().getUserId()).eq(ClosedPersonCompanyEntity::getId, companyPersonId).update();
    }

    @Override
    public IPage<ClosedPersonCompanyEntity> queryAppCompanyPersonSelfPage(Page page, ClosedPersonCompanyDTO closedPersonCompanyDTO) {
        final LambdaQueryWrapper<ClosedPersonCompanyEntity> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(ClosedPersonCompanyEntity::getApplyUserId, SecurityUtils.getUserId());
        wrapper.eq(ObjUtil.isNotNull(closedPersonCompanyDTO.getOrgId()), ClosedPersonCompanyEntity::getOrgId, closedPersonCompanyDTO.getOrgId());
        wrapper.eq(ObjUtil.isNotNull(closedPersonCompanyDTO.getAuditStatus()), ClosedPersonCompanyEntity::getAuditStatus, closedPersonCompanyDTO.getAuditStatus());
        wrapper.eq(StrUtil.isNotBlank(closedPersonCompanyDTO.getEmployeeType()), ClosedPersonCompanyEntity::getEmployeeType, closedPersonCompanyDTO.getEmployeeType());
        wrapper.like(StrUtil.isNotBlank(closedPersonCompanyDTO.getKeyword()), ClosedPersonCompanyEntity::getName, closedPersonCompanyDTO.getKeyword())
                .or().like(StrUtil.isNotBlank(closedPersonCompanyDTO.getKeyword()), ClosedPersonCompanyEntity::getCardNo, closedPersonCompanyDTO.getKeyword())
                .or().like(StrUtil.isNotBlank(closedPersonCompanyDTO.getKeyword()), ClosedPersonCompanyEntity::getCompanySocialCode, closedPersonCompanyDTO.getKeyword());
        wrapper.orderByAsc(ClosedPersonCompanyEntity::getOrgId);

        return this.page(page, wrapper);
    }

    @Override
    public IPage<ClosedPersonCompanyEntity> queryAppCompanyPersonAuditPage(Page page, List<Integer> auditStatusList, ClosedPersonCompanyDTO closedPersonCompanyDTO) {
        final LambdaQueryWrapper<ClosedPersonCompanyEntity> wrapper = Wrappers.lambdaQuery();
        wrapper.in(CollUtil.isNotEmpty(auditStatusList), ClosedPersonCompanyEntity::getAuditStatus, auditStatusList);
        wrapper.eq(ObjUtil.isNotNull(closedPersonCompanyDTO.getAuditStatus()), ClosedPersonCompanyEntity::getAuditStatus, closedPersonCompanyDTO.getAuditStatus());
        wrapper.eq(ObjUtil.isNotNull(closedPersonCompanyDTO.getOrgId()), ClosedPersonCompanyEntity::getOrgId, closedPersonCompanyDTO.getOrgId());
        wrapper.eq(ObjUtil.isNotNull(closedPersonCompanyDTO.getAuditStatus()), ClosedPersonCompanyEntity::getAuditStatus, closedPersonCompanyDTO.getAuditStatus());
        wrapper.eq(StrUtil.isNotBlank(closedPersonCompanyDTO.getEmployeeType()), ClosedPersonCompanyEntity::getEmployeeType, closedPersonCompanyDTO.getEmployeeType());
        wrapper.like(StrUtil.isNotBlank(closedPersonCompanyDTO.getKeyword()), ClosedPersonCompanyEntity::getName, closedPersonCompanyDTO.getKeyword())
                .or().like(StrUtil.isNotBlank(closedPersonCompanyDTO.getKeyword()), ClosedPersonCompanyEntity::getCardNo, closedPersonCompanyDTO.getKeyword())
                .or().like(StrUtil.isNotBlank(closedPersonCompanyDTO.getKeyword()), ClosedPersonCompanyEntity::getCompanySocialCode, closedPersonCompanyDTO.getKeyword());
        wrapper.orderByAsc(ClosedPersonCompanyEntity::getOrgId);
        return this.page(page, wrapper);
    }

    @Override
    public ValidateImportBO<ClosedPersonCompanyExcelDTO> validateImport(List<ClosedPersonCompanyExcelDTO> excelDTOList) {
        ValidateImportBO<ClosedPersonCompanyExcelDTO> bo = new ValidateImportBO<>();
        List<ErrorMessage> errorMessageList = new ArrayList<>();
        List<ClosedPersonCompanyExcelDTO> saveList = new ArrayList<>();
        int successNum = 0;
        int failedNum = 0;

        for (ClosedPersonCompanyExcelDTO closedPersonCompanyExcelDTO : excelDTOList) {
            final String validateRes = ValidatorUtils.importValidateEntity(closedPersonCompanyExcelDTO);
            if (StrUtil.isEmpty(validateRes)) {
                successNum++;
                saveList.add(closedPersonCompanyExcelDTO);
            } else {
                failedNum++;
                errorMessageList.add(new ErrorMessage(closedPersonCompanyExcelDTO.getLineNum(), new HashSet<>(){
                    private static final long serialVersionUID = 2114050778826325599L;
                    {
                        add(validateRes);
                    }
                }));
            }
        }

        bo.setErrorMessages(errorMessageList);
        bo.setSaveList(saveList);
        bo.setSuccessNum(successNum);
        bo.setFailedNum(failedNum);
        return bo;
    }

    @Override
    public ClosedPersonCompanyEntity importDtoToEntity(ClosedPersonCompanyExcelDTO excelDto) {
        ClosedPersonCompanyEntity entity= new ClosedPersonCompanyEntity();
        BeanUtils.copyProperties(excelDto, entity);
        if (StrUtil.isNotBlank(excelDto.getSexStr())) {
            entity.setSex(DictResolver.getItemValueByLabel(ParkCloseSysDictEnum.gender, excelDto.getSexStr()));
        }
        if (StrUtil.isNotEmpty(excelDto.getOrgIdStr())) {
            entity.setOrgId(DictResolver.getItemValueByLabel(AdminDictEnum.sys_company, excelDto.getOrgIdStr(), Long::valueOf));
        }
        if (StrUtil.isNotBlank(excelDto.getEmployeeTypeStr())) {
            entity.setEmployeeType(DictResolver.getItemValueByLabel(ParkCloseSysDictEnum.close_employee_Type, excelDto.getEmployeeTypeStr()));
        }
        entity.setApplyUserId(SecurityUtils.getUserId());
        if (ObjUtil.isNull(entity.getApplyTime())) {
            entity.setApplyTime(Calendar.getInstance().getTime());
        }
        entity.setAuditStatus(VisitorDicConstant.CLOSE_VISITOR_AUDIT_STATUS_NOT_SUBMIT);
        return entity;
    }

    @Override
    public ClosedPersonCompanyExcelVO exportEntityToVo(ClosedPersonCompanyEntity entity) {
        ClosedPersonCompanyExcelVO excelVO = new ClosedPersonCompanyExcelVO();
        BeanUtils.copyProperties(entity, excelVO);
        excelVO.setAccountIdStr(ObjUtil.isNotNull(entity.getAccountId()) ? "已绑定" : "未绑定");
        return excelVO;
    }


}
